2 // adiumPurpleDnsRequest.m
5 // Created by Graham Booker on 2/24/07.
8 #import "adiumPurpleDnsRequest.h"
10 #include <libpurple/internal.h>
12 #include <sys/socket.h>
15 @interface AdiumPurpleDnsRequest : NSObject {
16 PurpleDnsQueryData *query_data;
17 PurpleDnsQueryResolvedCallback resolved_cb;
18 PurpleDnsQueryFailedCallback failed_cb;
23 + (AdiumPurpleDnsRequest *)lookupRequestForData:(PurpleDnsQueryData *)query_data;
24 - (id)initWithData:(PurpleDnsQueryData *)data resolvedCB:(PurpleDnsQueryResolvedCallback)resolved failedCB:(PurpleDnsQueryFailedCallback)failed;
25 - (void)startLookup:(id)sender;
26 - (void)lookupComplete:(NSValue *)resValue;
30 @implementation AdiumPurpleDnsRequest
32 static NSMutableDictionary *threads = nil;
38 threads = [[NSMutableDictionary alloc] init];
41 + (AdiumPurpleDnsRequest *)lookupRequestForData:(PurpleDnsQueryData *)query_data
43 return [threads objectForKey:[NSValue valueWithPointer:query_data]];
46 - (id)initWithData:(PurpleDnsQueryData *)data resolvedCB:(PurpleDnsQueryResolvedCallback)resolved failedCB:(PurpleDnsQueryFailedCallback)failed
53 resolved_cb = resolved;
59 [threads setObject:self forKey:[NSValue valueWithPointer:query_data]];
60 [self retain]; //Released in lookupComplete:
61 [NSThread detachNewThreadSelector:@selector(startLookup:) toTarget:self withObject:nil];
66 - (void)startLookup:(id)sender
68 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
69 struct addrinfo hints, *res;
72 AILog(@"Performing DNS resolve: %s:%d",purple_dnsquery_get_host(query_data),purple_dnsquery_get_port(query_data));
73 g_snprintf(servname, sizeof(servname), "%d", purple_dnsquery_get_port(query_data));
74 memset(&hints, 0, sizeof(hints));
76 /* This is only used to convert a service
77 * name to a port number. As we know we are
78 * passing a number already, we know this
79 * value will not be really used by the C
82 hints.ai_socktype = SOCK_STREAM;
83 errorNumber = getaddrinfo(purple_dnsquery_get_host(query_data), servname, &hints, &res);
84 if (errorNumber == 0) {
89 printf("dns[%d] Error: getaddrinfo returned %d\n", getpid(), rc);
90 dns_params.hostname[0] = '\0';
95 [self performSelectorOnMainThread:@selector(lookupComplete:) withObject:(success ? [NSValue valueWithPointer:res] : nil) waitUntilDone:NO];
99 - (void)lookupComplete:(NSValue *)resValue
102 //Cancelled, so take no action now that the lookup is complete.
104 } else if (success && resValue) {
105 //Success! Build a list of our results and pass it to the resolved callback
106 AILog(@"DNS resolve complete for %s:%d",purple_dnsquery_get_host(query_data),purple_dnsquery_get_port(query_data));
107 struct addrinfo *res, *tmp;
108 GSList *returnData = NULL;
110 res = [resValue pointerValue];
113 size_t addrlen = res->ai_addrlen;
114 struct sockaddr *addr = g_malloc(addrlen);
115 memcpy(addr, res->ai_addr, addrlen);
116 returnData = g_slist_append(returnData, GINT_TO_POINTER(addrlen));
117 returnData = g_slist_append(returnData, addr);
122 resolved_cb(query_data, returnData);
125 //Failure :( Send an error message to the failed callback
128 g_snprintf(message, sizeof(message), _("Error resolving %s:\n%s"),
129 purple_dnsquery_get_host(query_data), gai_strerror(errorNumber));
130 failed_cb(query_data, message);
133 //Release our retain in init...
137 //Can happen if we were cancelled
138 [threads removeObjectForKey:[NSValue valueWithPointer:query_data]];
144 //Can't stop an existing thread, so let it just die gracefully when it is done
147 //To avoid collisions and the like
148 [threads removeObjectForKey:[NSValue valueWithPointer:query_data]];
154 gboolean adiumPurpleDnsRequestResolve(PurpleDnsQueryData *query_data, PurpleDnsQueryResolvedCallback resolved_cb, PurpleDnsQueryFailedCallback failed_cb)
156 [[[AdiumPurpleDnsRequest alloc] initWithData:query_data resolvedCB:resolved_cb failedCB:failed_cb] autorelease];
160 void adiumPurpleDnsRequestDestroy(PurpleDnsQueryData *query_data)
162 [[AdiumPurpleDnsRequest lookupRequestForData:query_data] cancel];
165 static PurpleDnsQueryUiOps adiumPurpleDnsRequestOps = {
166 adiumPurpleDnsRequestResolve,
167 adiumPurpleDnsRequestDestroy
170 PurpleDnsQueryUiOps *adium_purple_dns_request_get_ui_ops(void)
172 return &adiumPurpleDnsRequestOps;